//实现 strStr() 函数。 
//
// 给定一个 haystack 字符串和一个 needle 字符串，在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如
//果不存在，则返回 -1。 
//
// 示例 1: 
//
// 输入: haystack = "hello", needle = "ll"
//输出: 2
// 
//
// 示例 2: 
//
// 输入: haystack = "aaaaa", needle = "bba"
//输出: -1
// 
//
// 说明: 
//
// 当 needle 是空字符串时，我们应当返回什么值呢？这是一个在面试中很好的问题。 
//
// 对于本题而言，当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。 
// Related Topics 双指针 字符串 
// 👍 622 👎 0

package com.everyday.algorithm.changyf.leetcode.editor.cn;

import java.util.Map;

public class ImplementStrstr {
    static int[] GetNext(char T[])
    {
        int[] next = new int[100];
        int j=0,k=-1;
        next[j]=k;
        while(j<T.length)
        {
            if(k==-1||T[j]==T[k])
            {
                j++;
                k++;
                next[j]=k;
            }
            else k=next[k];
        }
        return next;
    }
    public static void main(String[] args) {
        Solution solution = new ImplementStrstr().new Solution();
    }
    //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    //理解KMP算法：主要是needle字符串顺着haystack字符串滑动，遇到不匹配的字符串时，
    //应该将匹配状态回滚到一个最佳回滚位置，需要多使用一些空间来记录回滚的位置，关键就
    //在于怎么记录这个回滚的位置，目前见到两种记录方式。
    //1.第一种从百度获得，计算出next[]数组，记录了当匹配失败时回滚的位置。例如needle
    // 为[a,b,a,b,a]，那么next[]数组是[-1,0,0,1,2]，当haystack字符串为[a,b,a,b,c,d,...]
    // 且对比到c时，此时的匹配needle[3]，会回滚到next[3]记录的索引位置，即needle[next[3]]
    // => needle[1],然后比较下一个字符needle[2]和c,发现不符再回滚到-1，此时重新从d开始比较。
    // 特点是记录信息占用空间小，但是可能对比多次，如needle为[a,a,a,a],haystack为[a,a,a,c, ...]，
    // 此时需要与c对比多次，直到回滚至-1。
    //2.第二种从该题的解题思路中看到，与第一种不同的是使用了状态机的概念，用二维数组next[][]记录了状态以及回滚状态，
    //  不使用索引，而使用状态描述匹配情况，记录回滚位置，即next[状态][当前haystack字符]。状态从0到
    //  needle.length,比如同样对比到c时，因为needle中并没有c，所以应该直接从头开始与d对比，此时状态为4，
    //  则应回滚至状态next[4]['c'],然后重新从d开始。特点是占用空间较多但只需对比一次。
    //从解题中看到KMP算法其实是一种基于动态规划的算法
    public int strStr(String haystack, String needle) {
        if ("".equals(needle)){
            return 0;
        }

        int ret = -1;
        for (int i=0; i<haystack.length(); i++){
            if (ret != -1){
                break;
            }
            for (int j=0,k=i; haystack.length()-i>=needle.length() && j<needle.length(); j++,k++){
                if (haystack.charAt(k) != needle.charAt(j)){
                    break;
                }
                if (j == needle.length()-1){
                    ret = i;
                }
            }
        }
        return ret;
    }
}
//leetcode submit region end(Prohibit modification and deletion)
}